Programação Web

Aula 18 - Manipulando páginas com JavaScript




Helder Jefferson Ferreira da Luz

helder.luz@ifpr.edu.br

Objetivos

  • Entender como o JavaScript se conecta a uma página HTML
  • Aprender o que é o DOM (Document Object Model)
  • Selecionar elementos HTML usando diferentes métodos
  • Manipular o conteúdo e os estilos dos elementos
  • Reagir a interações do usuário, como cliques de botão

Importando JavaScript

O código JavaScript pode ser adicionado à página de duas formas:

  • Dentro das tags container <script>
  • Por meio de arquivo externo .js e importando com a tag <script>

Importando o JavaScript

Onde o script é adicionado influencia no funcionamento da página. O carregamento do script bloqueia a análise (parse) do resto da página até que ele termine.

Isso implica no código ser carregado antes do conteúdo HTML ao qual o JS interage.

Para contornar, é comum colocar o código JavaScript no fim do <body>, embora idealmente ele deva ser colocado no <head>.

Importando o JavaScript

O comportamento é definido pelos atributos da tag <script> :

  • async: a página e o script são carregados paralelamente e o script é executado assim que o download termina (podendo ocorrer antes do parse concluir)
  • defer: a página e o script são carregados paralelamente e o script é executado quando o parse finaliza.
  • default: o script é baixado e executado imediatamente, bloqueando o parse da página até finalizar o script.
<script src="index.js" defer></script>

Importando o JavaScript

<script>

Importando o JavaScript

<script async>

Importando o JavaScript

<script defer>

Manipulação de página

Com o JavaScript, podemos criar páginas dinâmicas e interativas. Ele nos permite:

  • Modificar todos os elementos e atributos HTML
  • Alterar todos os estilos CSS
  • Remover e adicionar novos elementos
  • Reagir a eventos do usuário (cliques, teclas, etc.)
  • Criar novos eventos na página

Para fazer tudo isso, interagimos com uma estrutura chamada DOM.

DOM

DOM significa Document Object Model (Modelo de Objeto do Documento).

É uma representação em memória da estrutura de uma página HTML. O navegador cria essa representação em formato de árvore, onde cada elemento, atributo e texto é um "nó" (node).

O JavaScript pode acessar e manipular essa árvore de nós para alterar a página dinamicamente.

Árvore de elementos do HTML DOM

O Objeto document

O JavaScript nos dá acesso ao DOM através de um objeto global chamado document.

Este objeto é a porta de entrada para toda a estrutura da página. A partir dele, podemos acessar qualquer elemento, executar métodos para encontrar o que precisamos e iniciar a manipulação.

Qualquer operação no DOM começa com document.

// Acessando o elemento <body> da página
const corpoDaPagina = document.body;

// Acessando o título da página
console.log(document.title); 

Outros Objetos Importantes do DOM

Além do document, existem outros objetos globais que nos dão acesso a diferentes partes do ambiente do navegador:

  • window: O objeto global principal. Representa a janela do navegador. document é, na verdade, uma propriedade de window.

    • window.innerHeight / window.innerWidth: Altura e largura da área de conteúdo da janela.
    • window.alert(): Mostra um alerta.
  • navigator: Contém informações sobre o navegador do usuário (nome, versão, etc.).

    • navigator.userAgent

Outros Objetos Importantes do DOM

  • screen: Contém informações sobre a tela do usuário (resolução, etc.).

    • screen.width / screen.height
  • location: Contém informações sobre a URL atual e permite redirecionar a página.

    • location.href / location.reload()
  • history: Permite interagir com o histórico de navegação do usuário.

    • history.back() / history.forward()

Selecionando Elementos (A Abordagem Moderna)

A forma mais moderna e versátil de selecionar elementos é com querySelector e querySelectorAll. Eles usam a mesma sintaxe de seletores do CSS.

document.querySelector()
Retorna o primeiro elemento que corresponde ao seletor CSS especificado. Se nada for encontrado, retorna null.
document.querySelectorAll()
Retorna todos os elementos que correspondem ao seletor, em uma lista (NodeList). Se nada for encontrado, a lista estará vazia.

Selecionando Elementos - Exemplos

// Retorna o primeiro elemento com o id 'titulo'
const titulo = document.querySelector('#titulo');

// Retorna o primeiro elemento com a classe 'item'
const primeiroItem = document.querySelector('.item');

// Retorna o primeiro parágrafo <p>
const p = document.querySelector('p');

// Retorna TODOS os elementos com a classe 'item'
const todosItens = document.querySelectorAll('.item');

// Itera sobre a lista de itens
todosItens.forEach(item => {
  console.log(item);
});

Selecionando Elementos (A Abordagem Clássica)

Existem também métodos mais antigos e específicos para seleção. Você os encontrará em muitos códigos e projetos.

  • document.getElementById('id')
    • Retorna o único elemento com o ID especificado.
  • document.getElementsByClassName('classe')
    • Retorna uma coleção de elementos que possuem a classe especificada.
  • document.getElementsByTagName('tag')
    • Retorna uma coleção de elementos com a tag especificada (ex: 'p', 'div').

Observação: querySelector é geralmente preferível por sua versatilidade.

Manipulando Conteúdo

Uma vez que um elemento é selecionado, podemos ler ou alterar seu conteúdo.

  • elemento.innerHTML

    • Lê ou define o conteúdo HTML dentro de um elemento.
    • Cuidado: Usar innerHTML com dados de um usuário pode ser inseguro (risco de ataques XSS).
  • elemento.textContent

    • Lê ou define o conteúdo de texto de um elemento.
    • É mais seguro e performático se você precisa manipular apenas texto.

Exemplo - innerHTML vs textContent

<div id="exemplo"></div>
const div = document.querySelector('#exemplo');

// Usando textContent (mais seguro para texto)
div.textContent = 'Olá, Mundo!'; 
// Resultado: <div>Olá, Mundo!</div>

// Usando innerHTML (interpreta as tags)
div.innerHTML = '<strong>Olá, Mundo!</strong>';
// Resultado: <div><strong>Olá, Mundo!</strong></div>

Manipulando Atributos

Podemos também acessar e modificar os atributos de um elemento.

<img id="logo" src="logo_antigo.png" alt="Logo">
const imagem = document.querySelector('#logo');

// Lendo um atributo
console.log(imagem.src); // "logo_antigo.png"

// Modificando um atributo
imagem.src = 'logo_novo.png';
imagem.alt = 'Novo Logo da Empresa';

Manipulando Estilos

Os estilos CSS de um elemento podem ser alterados através da propriedade style. As propriedades CSS são escritas em camelCase em JavaScript (ex: background-color vira backgroundColor).

<h1 id="titulo">Título da Página</h1>
const titulo = document.querySelector('#titulo');

// Alterando o estilo do elemento
titulo.style.color = 'blue';
titulo.style.backgroundColor = 'lightgray';
titulo.style.fontSize = '32px';
titulo.style.borderBottom = '2px solid blue';

Manipulando Classes com classList

Em vez de alterar estilos um por um com elemento.style, a melhor prática é ter classes CSS prontas e apenas gerenciá-las com JavaScript.

A propriedade classList nos dá métodos para isso:

elemento.classList.add('classe') // - Adiciona a classe especificada.
elemento.classList.remove('classe') // - Remove a classe.

/* - Adiciona se não tiver, remove se tiver. 
Perfeito para menus, modo escuro, etc. */
elemento.classList.toggle('classe') 

// - Verifica se o elemento possui a classe (retorna `true` ou `false`).
elemento.classList.contains('classe') 

HTML DOM - Eventos

Pode-se usar o JavaScript para atrelar eventos aos elementos HTML, como o elemento de clicar.

Exemplo - onclick
document.querySelector("#limpa").onclick = function clear() { 
  // código 
}

HTML DOM - Eventos

Exemplo 2 - addEventListener()
document.querySelector("#limpa").addEventListener("click", limpa);

function limpa() {
  // código
}

HTML DOM - Eventos

onclick e similares permitem atrelar somente uma função ao evento.
addEventListener permite adicionar várias funções ao mesmo evento.

HTML DOM - Eventos

Há diversos outros eventos além do clique simples do mouse que a sua página pode reagir, como clique duplo, pressionamento de tecla, movimento do mouse, dentre outros.

Acesse o link para uma lista de eventos:
https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events

Leitura de dados de formulários

A forma mais robusta de capturar dados é ouvindo o evento submit do próprio formulário. Isso garante que a captura funcione independentemente de como o formulário é enviado (clique no botão ou tecla Enter).

<form id="formulario">
    <label for="name">Nome:</label><input type="text" id="name" name="name">
    <label for="email">Email:</label><input type="email" id="email" name="email">
    <label for="message">Mensagem:</label><textarea id="message" name="message"></textarea>
    <button type="submit">Enviar</button>
</form>
<p id="resultado"></p>

Observação: O atributo name é essencial para que os campos sejam reconhecidos pelo formulário, especialmente em abordagens mais diretas.

Leitura de dados de formulários

Abordagem 1: Lendo cada campo por seu id

const form = document.querySelector('#formulario');

form.addEventListener('submit', (e) => {
  e.preventDefault(); // Evita o recarregamento da página

  const name = document.querySelector('#name').value;
  const email = document.querySelector('#email').value;
  const message = document.querySelector('#message').value;
  const dadosMensagem = { name, email, message };
  console.log(dadosMensagem);
});

Leitura de dados de formulários

Abordagem 2: Acessando os elementos pelo name

const form = document.querySelector('#formulario');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  // Acessa os campos pelo atributo 'name'
  const name = form.elements.name.value;
  const email = form.elements.email.value;
  const message = form.elements.message.value;
  const dadosMensagem = { name, email, message };
  console.log(dadosMensagem);
  form.reset();
});

Leitura de dados de formulários

Abordagem 3: Usando desestruturação

const form = document.querySelector('#formulario');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  // Desestruturação a partir de form.elements
  const { name, email, message } = form.elements;
  const dadosMensagem = { 
    name: name.value, 
    email: email.value, 
    message: message.value 
  };
  console.log(dadosMensagem);
  form.reset();
});

Leitura de dados (A Forma Mais Moderna)

Abordagem 4: Usando FormData

A API FormData foi criada para capturar os valores de um formulário de forma automática. É a abordagem mais limpa e escalável.

const form = document.querySelector('#formulario');

form.addEventListener('submit', (e) => {
  e.preventDefault();
  
  const formData = new FormData(form);
  
  // Converte os dados para um objeto simples
  const dados = Object.fromEntries(formData.entries());
  
  console.log(dados); // { name: '...', email: '...', message: '...' }
  form.reset();
});

Escrevendo o resultado

Apresentando o resultado em um elemento HTML da página.

const form = document.querySelector('#formulario');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const name = form.elements.name.value;
  const email = form.elements.email.value;
  const message = form.elements.message.value;
  form.reset();

  const resultado = document.querySelector('#resultado');
  resultado.textContent = `Nome: ${name}, Email: ${email}, Mensagem: ${message}`;
});

Dúvidas? 🤔

Exercícios

  1. Faça os exercícios JS HTML DOM
    https://www.w3schools.com/js/exercise_js.asp?filename=exercise_js_dom_html1
  2. Faça uma página HTML com um campo de texto, um botão e um parágrafo. Ao clicar no botão, o texto do campo de texto deve ser apresentado no parágrafo.
  3. Faça uma página com 5 parágrafos e um botão. Ao clicar no botão, ele deve atribuir os valores do 1 ao 5 respectivamente em cada parágrafo.
  4. Faça uma página com 2 campos para número, um botão e um parágrafo. Ao clicar no botão, os valores de cada campo devem ser somados e o resultado apresentado no parágrafo.

Exercícios

  1. Crie uma página com uma <textarea> e um parágrafo logo abaixo que servirá como contador. Usando o evento input, atualize o parágrafo em tempo real para mostrar quantos caracteres o usuário já digitou. Ex: "Caracteres: 75".
  2. Crie uma página com uma imagem principal e uma pequena lista de 3 imagens "miniatura" abaixo. Ao clicar em uma das miniaturas, o src da imagem principal deve ser atualizado para exibir a imagem da miniatura que foi clicada.
  3. Crie uma página com um conteúdo qualquer (títulos, parágrafos) e um botão "Alternar Modo Escuro". No seu CSS, crie uma classe .dark-mode que aplique um fundo escuro e texto claro ao <body>. Usando JavaScript, faça com que o clique no botão adicione ou remova a classe .dark-mode do <body>, utilizando classList.toggle().